<?php
/*
 * @Create By: Vscode
 * @Author: falcon
 * @Date: 2021-02-16 22:57:27
 * 库存分配定时任务 ：： 把新的代采购状态的库存分配到订单中
 */

namespace application\timer;

use application\model\PdoModel;
use application\depend\PhpRedis;
use application\depend\Applog;

class StocksDistribution{

    public function main(){
        // 可配货产品”页面，该页面汇总的数据是：“缺货产品”中“1号仓库”有库存的产品的可配货数量情况
        $startTime = time();
        $sql = "select sku,order_number,quantity,cumulative_quantity,alsobuy,purchase_quantity,purchase_order_date as order_date,salesman from order_info where status=2 and sales_return<>1 order by purchase_order_date,order_number asc"; // purchase_order_date 是2021-03-20 新增的字段;专门记录新建订单完成到代采购订单的时间
        $res = PdoModel::selectData($sql,[],"采购单状态=2的订单");
        if(!empty($res) && is_array($res)){
            $combineOrderInf = combine_multi_sku($res);// 整合订单编号
            $waitPurchaseDetails = $this->filter_zero_alsobuy($combineOrderInf); // 过滤 alsobuy = 0 的 也就是 quantity - cumulative_quantity = 0 的数据
           
            if(empty($waitPurchaseDetails)){// 如果过滤后 数据为空， 就清空掉数据
                PhpRedis::set('distribut_stock_for_wait_purchase_order',null);
                Applog::debugLogs(['title'=>'库存分配给代采购订单数据为空！']);
                return ;
            }
            
            $skuAvaiAmount = $this->sku_stocks_shelf($waitPurchaseDetails); // 虚拟仓的货位和库存数信息  key => sku , v['stocks'] , v['shelf']

            //分配现有的库存 并将 分配好的结果 放入redis中
            $this->distribut_stock_on_ordernumber($skuAvaiAmount,$waitPurchaseDetails); // 计算 可配货产品数量（按订单分配库存数）
        }// if
        $endTime = time();
        Applog::infoLog(['title' => '统计可配货定时任务花费时间','time-spend' => $endTime-$startTime.'秒','date'=>date('Y-m-d H:i:s')]);
    }// func 

    // 过滤 以满足需求的 数据
    public function filter_zero_alsobuy($combineOrderInf){
        foreach($combineOrderInf as $k=>$v){
            if(($v['quantity'] - $v['cumulative_quantity']) <= 0) {
                unset($combineOrderInf[$k]); //删除满足采购需求数的订单信息
            }// if
        }// foreach

        $combineOrderInf = array_values($combineOrderInf);
        return $combineOrderInf;
    }// func

    /// 库存 和 货位
    public function sku_stocks_shelf($waitPurchaseDetails){
        /**
         * 根据过滤号的 代采购订单详情信息， 获取虚拟仓的 库存数信息 和 货位
         * 某SKU虚拟仓库存数 >= 所有订单某sku总数 自动全分配好
         * 某SKU虚拟仓库存数 < 所有订单某sku总数 按时间先后分配库存，把缺货的信息提炼出来放到 实际缺货列表中
         */

        $accResult = []; //配件仓信息
        $result = []; //成品仓信息

        //根据SKU 获取可配货数量 和 货位
        $skuString = '';
        foreach($waitPurchaseDetails as $v){
            if(false === strpos($skuString,"'".strtoupper($v['sku'])."'")){ // 如果不存在就加入
                $skuString .= "'".strtoupper($v['sku'])."',";
            }// if
        }// foreach
        if(!empty($skuString)) $skuString = rtrim($skuString,',');

        $sql = "select id,sku,available_stock,product_location from product where sku in ({$skuString})";
        $result = PdoModel::selectData($sql,[],'批量查询1号虚拟库存');
       
        if(!empty($result) && is_array($result)){
            $accPartSku = [];
            //检查是否有部分sku 没有 id 的
            foreach($waitPurchaseDetails as $v){
                foreach($result as $vv){
                    if(strtoupper($v['sku']) == strtoupper($vv['sku'])){// 如果不存在，就记录下
                        continue 2; //跳出当前循环， 继续外面那层循环
                    }// if 
                }//foreach
                if(!in_array(strtoupper($v['sku']),$accPartSku)){
                    $accPartSku[] = strtoupper($v['sku']); // 确保唯一
                }
            }//foreach 2

            if(!empty($accPartSku)){ // 代表订单中有 半成品 存在
                $accSkuString = '';
                foreach($accPartSku as $v){
                    $accSkuString .= "'".strtoupper($v)."',";
                }// foreach
                if(!empty($accSkuString)) $accSkuString = rtrim($accSkuString,',');

                $sql = "select id,sku,available_stock,product_location from product_acc where sku in ({$accSkuString})";
                $accResult = PdoModel::selectData($sql,[],'批量查询10号虚拟库存');
            }// if
        }else{// 到这里 很可能全都是 配件了
            $sql = "select id,sku,available_stock,product_location from product_acc where sku in ({$skuString})";
            $accResult = PdoModel::selectData($sql,[],'批量查询10号虚拟库存');
        }//else

        // 统一装配 库存数信息 和 货架号
        if(empty($result)) return $accResult;
        if(!empty($result) && !empty($accResult)){
            //合并下
            foreach($accResult as $v){
                $result[] = $v;
            }
            return $result;
        }// if
        
        if(!empty($result)) return $result; // accResult 为空
        return $accResult;
    }// func

    // 按订单先后 分配 库存数
    public function distribut_stock_on_ordernumber($skuAvaiAmount,&$waitPurchaseDetails){
        // 开始从上到下分配日期
        $goToPurchase = [];
        
        foreach($skuAvaiAmount as &$v){
            $skuTotalStocks = $v['available_stock'];
            foreach($waitPurchaseDetails as &$vv){
                if(strtoupper($v['sku']) == strtoupper($vv['sku'])){ // 匹配到了对应的SKU
                    $vv['product_location'] = isset($v['product_location'])?$v['product_location']:'';
                    if(($vv['quantity']-$vv['cumulative_quantity'])<=$skuTotalStocks){ // 库存仍然够用
                        $vv['available_num'] = $vv['quantity']-$vv['cumulative_quantity']; // 分配的库存数 就是 除开已采购数后 剩余的差数
                        $vv['still_need'] = 0;  // 如果库存仍然够用，缺货数量 = 0
                        $skuTotalStocks -= $vv['available_num']; // 分配完后， 库存减扣；  未入数据库
                    }else{ // 库存不足了 就把剩余的给它
                        $vv['available_num'] = $skuTotalStocks; // 可能是0  也可能＞0; 赋值完后 直接清0
                        $vv['still_need'] = $vv['quantity'] - $vv['cumulative_quantity'] - $skuTotalStocks;  // 缺货数量 = 调整数量 - 采购数量 - 可配货产品数量
                        $skuTotalStocks = 0;
                    }//else
                }// if
            }//foreach 
        }// foreach2

        foreach($waitPurchaseDetails as $k=>$v){
            if(isset($v['available_num']) && $v['available_num']==0 && $v['still_need']>0){
                $goToPurchase[] = $v;
            }
            // if(empty($v['available_num'])){ // 这里empty 也会包含上面那种情况 不合适
            if(!isset($v['available_num'])){
                unset($waitPurchaseDetails[$k]);
            }
        }//foreach
        
        // 将 $goToPurchase 组装进 PurchaseList数组中
        if(!empty($goToPurchase)){
            PhpRedis::set('go_to_purchase_list',$goToPurchase);
        }else{
            PhpRedis::set('go_to_purchase_list',null);
        }
        
        
        $waitPurchaseDetails = array_values($waitPurchaseDetails);
        if(!empty($waitPurchaseDetails)){
            PhpRedis::set('distribut_stock_for_wait_purchase_order',$waitPurchaseDetails);
        }else{
            PhpRedis::set('distribut_stock_for_wait_purchase_order',null);
        }//else
    }// func
}//class